package aerie.servlet;

import aerie.Container;
import aerie.context.AerieContext;
import aerie.context.AerieContextPool;
import aerie.controller.Controller;
import aerie.controller.ControllerPool;
import aerie.filter.FilterPool;
import aerie.fs.FSNeedle;
import groovy.util.ResourceException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class RequestBinding {
    private HttpServletRequest request;
    private HttpServletResponse response;
    private FSNeedle fsNeedle;
    private ControllerPool controllerPool;
    private AerieContextPool aerieContextPool;
    private FilterPool filterPool;
    private UriParser uriParser;
    private AerieContext aerieContext;

    public RequestBinding(HttpServletRequest request, HttpServletResponse response,
                          Container container) throws ResourceException {
        this.request = request;
        this.response = response;
        this.fsNeedle = container.getFsNeedle();
        this.controllerPool = container.getControllerPool();
        this.aerieContextPool = container.getAerieContextPool();
        this.filterPool = container.getFilterPool();
        this.uriParser = new UriParser(request.getRequestURI(), getAerieContext());
    }

    public AerieContext getAerieContext() throws ResourceException {
        if (aerieContext == null) {
            String uri = request.getRequestURI();
            String contextPath = request.getContextPath();
            aerieContext = aerieContextPool.getAerieContext(contextNameFrom(uri, contextPath));
            aerieContext.webAppContext = contextPath;
        }
        return aerieContext;
    }

    public Controller getController() throws ResourceException {
        final Controller controller = controllerPool.getInstanceOf(uriParser.extractController());
        controller.init(this);
        return controller;
    }

    public String getAction() {
        return uriParser.extractAction();
    }

    public String getParameter() {
        return uriParser.extractParameter();
    }

    public HttpServletRequest getRequest() {
        return request;
    }

    public HttpServletResponse getResponse() {
        return response;
    }

    public FSNeedle getApplicationResources() {
        return fsNeedle;
    }

    public List getFiltersForRequest() throws ResourceException {
        //noinspection unchecked
        List filterNames = new ArrayList(aerieContext.filters);
        //noinspection unchecked
        filterNames.addAll(getController().getFilters());
        List filters = new ArrayList();
        //noinspection ForLoopReplaceableByForEach
        for (Iterator it = filterNames.iterator(); it.hasNext();) {
            //noinspection unchecked
            filters.add(filterPool.getFilter((String) it.next()));
        }
        return filters;
    }

    private String contextNameFrom(String uri, String  contextPath) {
        String[] tokens = uri.split("/");
        if (contextPath.equals("/")) {
            return tokens.length > 1 ? tokens[1] : "";
        } else {
            return tokens.length > 2 ? tokens[2] : "";
        }
    }
}
